#include "server_correspond.h"

SOCKET server_socket = INVALID_SOCKET; // 服务器Socket

/* 初始化服务器通信
    * 该函数用于初始化服务器通信模块
    * @return 如果初始化成功返回0，失败返回1
*/
uint8 server_correspond_init(void) {
    WSADATA wsaData;
    int ret = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (ret != 0) {
        printf("WSAStartup failed: %d\n", ret);
        return 1;
    }
    // 初始化服务器通信模块
    server_log(LOG_SYSTEM, "Server correspond module initialized.");
    
    // 初始化Socket
    server_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (server_socket == INVALID_SOCKET) {
        server_log(LOG_SYSTEM, "Failed to create socket: %d", WSAGetLastError());
        return 1; // 初始化失败
    }

    // 为方便开发调试，设置端口可重用，减少等待时间
    int on = 1;
    if (setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
        server_log(LOG_SYSTEM, "Failed to set socket options: %d", WSAGetLastError());
        closesocket(server_socket);
        return 1; // 初始化失败
    }
    // 设置服务器地址端口号
    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(system_config.server_port); // 使用配置的端口号
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);    // 绑定到所有可用的网络接口
    if (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
        server_log(LOG_SYSTEM, "Failed to bind socket: %d", WSAGetLastError());
        closesocket(server_socket);
        return 1; // 初始化失败
    }
    // 开始监听
    if (listen(server_socket, system_config.max_connections) == -1) {
        server_log(LOG_SYSTEM, "Failed to listen on socket: %d", WSAGetLastError());
        closesocket(server_socket);
        return 1; // 初始化失败
    }
    
    return 0; // 初始化成功
}

/* 关闭服务器通信
    * 该函数用于关闭服务器通信模块
    * @return 如果关闭成功返回0，失败返回1
*/
uint8 server_correspond_close(void) {
    if (server_socket != INVALID_SOCKET) {
        closesocket(server_socket);
        server_socket = INVALID_SOCKET;
    }
    return 0; // 关闭成功
}

/* 接收客户端连接请求
    * 该函数用于接受客户端连接请求
    * @return 返回一个有效的Socket，如果失败返回INVALID_SOCKET
*/
SOCKET  server_correspond_accept_socket(void) {
    // 先检查服务器Socket是否有效
    if (server_socket == INVALID_SOCKET) {
        server_log(LOG_SYSTEM, "Server socket is not initialized.");
        // 断言
        server_assert(server_socket == INVALID_SOCKET);
        return INVALID_SOCKET; // 如果服务器Socket无效，返回INVALID_SOCKET
    }
    // 接受客户端连接请求
    SOCKET accept_socket = INVALID_SOCKET; // 定义接收Socket

    struct sockaddr_in accept_sockaddr; //定义accept IP地址结构
    socklen_t addrlen = sizeof(accept_sockaddr);
    memset(&accept_sockaddr, 0, addrlen);
    
    accept_socket = accept(server_socket, (struct sockaddr*)&accept_sockaddr, &addrlen);

    if (accept_socket == INVALID_SOCKET) {
        server_log(LOG_SYSTEM, "Failed to accept client socket: %d", WSAGetLastError());
        return INVALID_SOCKET;
    }
    return accept_socket;
}

/* 服务器通信事件处理函数
    * 该函数用于处理服务器通信事件
    * @param client_socket 客户端Socket
*/
void server_correspond_event_handler(SOCKET client_socket, char * client_ip) {
    // 先检查客户端Socket是否有效
    if (client_socket == INVALID_SOCKET) {
        server_log(LOG_SYSTEM, "Client socket is invalid.");
        // 断言
        server_assert(client_socket == INVALID_SOCKET);
        return; // 如果客户端Socket无效，直接返回
    }
    uint8  client_login_flag = 0; // 客户端登录标志
    uint32 client_session = 0;    // 客户端会话ID
    User * client_login_user = (User *)malloc(sizeof(User)); // 客户端用户信息
    while (1) {
        // 处理客户端请求
        CorrespondDataHead head;
        int recv_result = recv(client_socket, &head, sizeof(head), 0);
        if (recv_result < 0) {
            server_log(LOG_SYSTEM, "Failed to receive data from client: %d", WSAGetLastError());
            closesocket(client_socket);
            return;
        }else if (recv_result == 0) {
            server_log(LOG_SYSTEM, "Client with ip %s disconnected." , client_ip);
            closesocket(client_socket);
            return;
        }

        // 处理接收到的数据
        switch (head.type) {
            // ============================= 登录 =============================
            case CORRESPOND_DATA_TYPE_LOGIN:{
                // 接收登录数据
                CorrespondDataLogin login_data;
                if(recv(client_socket, &login_data, sizeof(login_data), 0) <= 0) {
                    server_log(LOG_SYSTEM, "Failed to receive login data from client: %d", WSAGetLastError());
                    closesocket(client_socket);
                    return;
                }
                // 处理登录请求
                UserFunctionReturn result = server_user_login(login_data.user_id, &(login_data.password[0]), client_login_user);
                if (result != LOGIN_SUCCESS) {
                    server_log(LOG_SYSTEM, "Login failed for user ID %u.", login_data.user_id);
                }else {
                    server_log(LOG_SYSTEM, "User ID %u logged in successfully from IP: %s.", login_data.user_id, client_ip);
                }
                // 发送登录结果
                CorrespondDataLoginBack login_back_data;
                login_back_data.result = result;
                login_back_data.user_id = client_login_user->id;
                wcscpy(login_back_data.name, client_login_user->name);
                if (send(client_socket, &login_back_data, sizeof(login_back_data), 0) <= 0) {
                    server_log(LOG_SYSTEM, "Failed to send login response to client: %d", WSAGetLastError());
                    closesocket(client_socket);
                    return;
                }
                client_login_flag = 1; // 登录成功
                break;
            }
            // ============================= 注销 =============================
            case CORRESPOND_DATA_TYPE_LOGOUT:{
                // 接收注销数据
                CorrespondDataLogout logout_data;
                if(recv(client_socket, &logout_data, sizeof(logout_data), 0) <= 0) {
                    server_log(LOG_SYSTEM, "Failed to receive logout data from client: %d", WSAGetLastError());
                    closesocket(client_socket);
                    return;
                }
                // 处理注销请求
                if (!client_login_flag) {
                    server_log(LOG_SYSTEM, "Client with IP %s is not logged in.", client_ip);
                    CorrespondDataLogoutBack logout_back_data;
                    logout_back_data.user_id = logout_data.user_id;
                    logout_back_data.result = LOGOUT_USER_NOT_LOGIN; // 用户未登录
                    // 发送注销结果
                    if (send(client_socket, &logout_back_data, sizeof(logout_back_data), 0) <= 0) {
                        server_log(LOG_SYSTEM, "Failed to send logout response to client: %d", WSAGetLastError());
                        closesocket(client_socket);
                        return;
                    }
                } else {
                    CorrespondDataLogoutBack logout_back_data;
                    logout_back_data.user_id = logout_data.user_id;
                    logout_back_data.result = LOGOUT_SUCCESS; // 注销成功
                    // 发送注销结果
                    if (send(client_socket, &logout_back_data, sizeof(logout_back_data), 0) <= 0) {
                        server_log(LOG_SYSTEM, "Failed to send logout response to client: %d", WSAGetLastError());
                        closesocket(client_socket);
                        return;
                    }
                    client_login_flag = 0; // 注销成功，清除登录标志
                    server_log(LOG_SYSTEM, "User ID %u logged out successfully from IP: %s.", logout_data.user_id, client_ip);
                }
                break;
            }
            // ============================= 注册 =============================
            case CORRESPOND_DATA_TYPE_REGISTER:{
                // 接收注册数据
                CorrespondDataRegister register_data;
                if(recv(client_socket, &register_data, sizeof(register_data), 0) <= 0) {
                    server_log(LOG_SYSTEM, "Failed to receive register data from client: %d", WSAGetLastError());
                    closesocket(client_socket);
                    return;
                }
                // 处理注册请求
                uint8 register_result = server_add_user(&(register_data.user));
                CorrespondDataRegisterBack register_back_data;
                register_back_data.result = register_result;
                register_back_data.user_id = register_data.user.id;
                // 发送注册结果
                if (send(client_socket, &register_back_data, sizeof(register_back_data), 0) <= 0) {
                    server_log(LOG_SYSTEM, "Failed to send register response to client: %d", WSAGetLastError());
                    closesocket(client_socket);
                    return;
                }
                break;
            }
            // ============================= 借阅 =============================
            case CORRESPOND_DATA_TYPE_BORROW:{
                // 接收借书数据
                CorrespondDataBorrow borrow_data;
                if(recv(client_socket, &borrow_data, sizeof(borrow_data), 0) <= 0) {
                    server_log(LOG_SYSTEM, "Failed to receive borrow data from client: %d", WSAGetLastError());
                    closesocket(client_socket);
                    return;
                }
                // 处理借书请求
                ObjectFunctionReturn borrow_result = server_lend_object(borrow_data.object_id, borrow_data.count, client_login_user);
                CorrespondDataBorrowBack borrow_back_data;
                borrow_back_data.result = borrow_result;
                // 发送借书结果
                if (send(client_socket, &borrow_back_data, sizeof(borrow_back_data), 0) <= 0) {
                    server_log(LOG_SYSTEM, "Failed to send borrow response to client: %d", WSAGetLastError());
                    closesocket(client_socket);
                    return;
                }
                if (borrow_result == BOOK_LEND_SUCCESS) {
                    server_log(LOG_SYSTEM, "User ID %u borrowed book ID %u successfully from IP: %s.", client_login_user->id, borrow_data.object_id, client_ip);
                } else {
                    server_log(LOG_SYSTEM, "User ID %u failed to borrow book ID %u from IP: %s. Error code: %d", client_login_user->id, borrow_data.object_id, client_ip, borrow_result);
                }
                break;
            }
            // ============================= 归还 =============================
            case CORRESPOND_DATA_TYPE_RETURN:{
                // 接收还书数据
                CorrespondDataReturn return_data;
                if(recv(client_socket, &return_data, sizeof(return_data), 0) <= 0) {
                    server_log(LOG_SYSTEM, "Failed to receive return data from client: %d", WSAGetLastError());
                    closesocket(client_socket);
                    return;
                }
                // 处理还书请求
                ObjectFunctionReturn return_result = server_return_object(return_data.object_id, return_data.count, client_login_user);
                CorrespondDataReturnBack return_back_data;
                return_back_data.result = return_result;
                // 发送还书结果
                if (send(client_socket, &return_back_data, sizeof(return_back_data), 0) <= 0) {
                    server_log(LOG_SYSTEM, "Failed to send return response to client: %d", WSAGetLastError());
                    closesocket(client_socket);
                    return;
                }
                if (return_result == BOOK_RETURN_SUCCESS) {
                    server_log(LOG_SYSTEM, "User ID %u returned book ID %u successfully from IP: %s.", client_login_user->id, return_data.object_id, client_ip);
                } else {
                    server_log(LOG_SYSTEM, "User ID %u failed to return book ID %u from IP: %s. Error code: %d", client_login_user->id, return_data.object_id, client_ip, return_result);
                }
                break;
            }
            // ============================= 续借 =============================
            case CORRESPOND_DATA_TYPE_RENEW_BOOK:{
                // 接收续借数据
                CorrespondDataRenew renew_data;
                if(recv(client_socket, &renew_data, sizeof(renew_data), 0) <= 0) {
                    server_log(LOG_SYSTEM, "Failed to receive renew data from client: %d", WSAGetLastError());
                    closesocket(client_socket);
                    return;
                }
                // 处理续借请求
                ObjectFunctionReturn renew_result = server_renew_object(renew_data.record_list_number, client_login_user);
                CorrespondDataRenewBack renew_back_data;
                renew_back_data.result = renew_result;
                // 发送续借结果
                if (send(client_socket, &renew_back_data, sizeof(renew_back_data), 0) <= 0) {
                    server_log(LOG_SYSTEM, "Failed to send renew response to client: %d", WSAGetLastError());
                    closesocket(client_socket);
                    return;
                }
                server_log(LOG_SYSTEM, "User ID %u renewed book ID %u successfully from IP: %s.", client_login_user->id, renew_data.record_list_number, client_ip);
                break;
            }
            // ============================= 查询图书 =============================
            case CORRESPOND_DATA_TYPE_QUERY_BOOK:{
                // 接收查询图书数据
                CorrespondDataQuery query_data;
                if(recv(client_socket, &query_data, sizeof(query_data), 0) <= 0) {
                    server_log(LOG_SYSTEM, "Failed to receive query data from client: %d", WSAGetLastError());
                    closesocket(client_socket);
                    return;
                }
                // 处理查询图书请求
                LibraryObjectPtrList * query_result = server_find_object_by_incomplete_name(query_data.name, query_data.is_sensitive);
                CorrespondDataQueryBack query_back_data;
                query_back_data.result = (query_result->total_objects > 0) ? 1 : 0; // 查询结果是否成功
                for (uint8 i = 0; i < 5; i++) {
                    if (i >= query_result->total_objects) {
                        // 如果查询结果不足5条，填充ID为0的无效数据
                        query_back_data.object[i].id = 0; // 设置ID为0表示无效
                    } else {
                        query_back_data.object[i] = *(query_result->first_node->object); // 返回前五条图书信息
                    }
                    query_result->first_node = query_result->first_node->next; // 移动到下一个节点
                }
                // 释放查询结果链表
                free(query_result);
                query_result = NULL; // 清空指针
                server_log(LOG_SYSTEM, "User ID %u queried books with name '%ls' from IP: %s. Result: %d", 
                        client_login_user->id, query_data.name, client_ip, query_back_data.result);
                // 发送查询结果
                if (send(client_socket, &query_back_data, sizeof(query_back_data), 0) <= 0) {
                    server_log(LOG_SYSTEM, "Failed to send query response to client: %d", WSAGetLastError());
                    closesocket(client_socket);
                    return;
                }
                break;
            }
            // ============================= 查询借阅图书 =============================
            case CORRESPOND_DATA_TYPE_QUERY_BORROWED_BOOK: {
                // 接收查询借阅图书数据
                CorrespondDataQueryBorrowRecord query_borrowed_data;
                if (recv(client_socket, &query_borrowed_data, sizeof(query_borrowed_data), 0) <= 0) {
                    server_log(LOG_SYSTEM, "Failed to receive query borrowed data from client: %d", WSAGetLastError());
                    closesocket(client_socket);
                    return;
                }
                // 处理查询借阅图书请求
                // 返回用户借阅的图书信息
                CorrespondDataQueryBorrowRecordBack query_borrowed_back_data;
                query_borrowed_back_data.result = 1; // 假设查询失败
                // 鉴定用户权限
                if (client_login_user->type != USER_TYPE_ADMINISTRATOR) {
                    // 如果不是管理员用户，检查用户ID是否匹配
                    if (query_borrowed_data.user_id != client_login_user->id) {
                        query_borrowed_back_data.result = 1; // 查询失败
                        // 发送查询结果
                        if (send(client_socket, &query_borrowed_back_data, sizeof(query_borrowed_back_data), 0) <= 0) {
                            server_log(LOG_SYSTEM, "Failed to send query borrowed response to client: %d", WSAGetLastError());
                            closesocket(client_socket);
                            return;
                        }
                    }
                }
                for (uint16 i = 0; i < BOOK_MANAGE_CONFIG_MAX_BORROW_BOOKS_CONFIG; i++) {
                    query_borrowed_back_data.record[i] = client_login_user->lent_objects[i]; // 返回借阅记录    
                }
                query_borrowed_back_data.result = 0; // 查询成功
                server_log(LOG_SYSTEM, "User ID %u queried borrowed books from IP: %s.", client_login_user->id, client_ip);
                // 发送查询结果
                if (send(client_socket, &query_borrowed_back_data, sizeof(query_borrowed_back_data), 0) <= 0) {
                    server_log(LOG_SYSTEM, "Failed to send query borrowed response to client: %d", WSAGetLastError());
                    closesocket(client_socket);
                    return;
                }
                break;
            }
            default:
                server_log(LOG_SYSTEM, "Unknown request type: %d", head.type);
                break;
        }
    }
}

